import { useLoader, useFrame } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { useEffect, useRef, useState } from 'react'
import { Canvas, useThree, extend } from '@react-three/fiber'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { Box3, Vector3, Group } from 'three'
import * as THREE from 'three'
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils'
extend({ OrbitControls })

const Orbit = () => {
  const { gl, camera } = useThree()
  return <orbitControls args={[camera, gl.domElement]} />
}

// 驱动 AnimationMixer 的组件（必须作为 Canvas 子组件使用）
const MixerUpdater = ({ mixerRef }: { mixerRef: React.MutableRefObject<THREE.AnimationMixer | null> }) => {
  useFrame((_, delta) => {
    if (mixerRef.current) mixerRef.current.update(delta)
  })
  return null
}

function MySelf() {
  const mySelfRef = useRef<Group | null>(null)
  const mixerRef = useRef<THREE.AnimationMixer | null>(null)
  const actionsRef = useRef<Record<string, THREE.AnimationAction>>({})
  const currentActionRef = useRef<THREE.AnimationAction | null>(null)
  const [isPlaying, setIsPlaying] = useState(false)
  const [availableActions, setAvailableActions] = useState<string[]>([])
  const [selectedAction, setSelectedAction] = useState<string>("")
  const model = useLoader(
    GLTFLoader,
    "https://models.readyplayer.me/68c0c1314b2306b86e9c3f8d.glb"
  )
  // 加载动作来源模型（FBX，有动画轨道）
  const waveSource = useLoader(FBXLoader, "/animations/Waving.fbx")
  const hiphopSource = useLoader(FBXLoader, "/animations/Wave Hip Hop Dance.fbx")
  const prayingSource = useLoader(FBXLoader, "/animations/Praying.fbx")
  const saluteSource = useLoader(FBXLoader, "/animations/Salute.fbx")
  const breakdanceSource = useLoader(FBXLoader, "/animations/Breakdance.fbx")

  // 方案A：将脚底作为锚点（把脚底放到世界原点 y=0，xz 居中）
  useEffect(() => {
    if (!model) return
    const root = model.scene
    const box = new Box3().setFromObject(root)
    const center = box.getCenter(new Vector3())
    // 将脚底放到 y=0，并让 x/z 居中到 0
    const offset = new Vector3(center.x, box.min.y, center.z)
    root.position.sub(offset)
  }, [model])

  // 生成动作 Action，并做基础调试（优先直接绑定；必要时再尝试重定向）
  useEffect(() => {
    if (!model || !waveSource) return
    // 创建并绑定到当前模型
    mixerRef.current = new THREE.AnimationMixer(model.scene)

    const sources = [
      { name: '挥手', src: waveSource },
      hiphopSource ? { name: '跳舞', src: hiphopSource } : null,
      prayingSource ? { name: '跪下求饶', src: prayingSource } : null,
      saluteSource ? { name: '敬礼', src: saluteSource } : null,
      breakdanceSource ? { name: '超级无敌螺旋升天', src: breakdanceSource } : null
    ].filter(Boolean) as Array<{ name: string; src: any }>

    const collected: string[] = []

    sources.forEach(({ name: srcName, src }) => {
      const clips = (src as any).animations || []
      console.log('[Anim] loaded clips from', srcName, ':', clips.map((c: any) => ({ name: c.name, tracks: c.tracks.length, duration: c.duration })))
      clips.forEach((clip: THREE.AnimationClip, index: number) => {
        let finalClip: THREE.AnimationClip = clip

        const sampleTrack = clip.tracks.find(t => typeof (t as any).name === 'string') as any
        const targetName = sampleTrack ? String(sampleTrack.name).split('.')[0] : null
        const directTarget = targetName ? model.scene.getObjectByName(targetName) : null

        if (!directTarget) {
          let sourceHasSkeleton = false
          let targetHasSkeleton = false
          ;(src as any).traverse?.((o: any) => { if (o.isSkinnedMesh && o.skeleton) sourceHasSkeleton = true })
          model.scene.traverse?.((o: any) => { if (o.isSkinnedMesh && o.skeleton) targetHasSkeleton = true })
          if (sourceHasSkeleton && targetHasSkeleton) {
            try {
              finalClip = SkeletonUtils.retargetClip((src as any), model.scene, clip)
            } catch (e) {
              console.warn('[Anim] retargetClip 失败(来源', srcName, '):', e)
            }
          }
        }

        const displayName = `${srcName}${clips.length>1?`_${index+1}`:''}`
        const action = mixerRef.current!.clipAction(finalClip)
        action.setLoop(THREE.LoopRepeat, Infinity)
        actionsRef.current[displayName] = action
        collected.push(displayName)
      })
    })

    setAvailableActions(collected)
    if (collected.length > 0) setSelectedAction(collected[0])
    return () => {
      mixerRef.current?.stopAllAction()
      mixerRef.current = null
      actionsRef.current = {}
    }
  }, [model, waveSource, hiphopSource])

  // 每帧驱动动画改到 Canvas 内部的 MixerUpdater 里

  const playAction = (name: string) => {
    if (!mixerRef.current) return
    const next = actionsRef.current[name]
    if (!next) return
    next.enabled = true
    next.clampWhenFinished = false
    next.setLoop(THREE.LoopRepeat, Infinity)
    const prev = currentActionRef.current
    const fadeOutDur = 0.25
    const fadeInDur = 0.25
    if (prev && prev !== next) {
      // 先淡出上一个，再启动下一个，避免两条动画叠加导致骨骼数值“乱飞”
      prev.fadeOut(fadeOutDur)
      setTimeout(() => {
        prev.stop()
        next.reset().fadeIn(fadeInDur).play()
      }, Math.ceil(fadeOutDur * 1000) + 30)
    } else if (!prev) {
      next.reset().fadeIn(fadeInDur).play()
    } else if (prev === next && !isPlaying) {
      next.reset().fadeIn(fadeInDur).play()
    }
    currentActionRef.current = next
    setIsPlaying(true)
  }

  const handleStop = () => {
    if (!mixerRef.current) return
    const prev = currentActionRef.current
    if (prev) {
      prev.fadeOut(0.2)
      setTimeout(() => prev.stop(), 220)
    }
    mixerRef.current.stopAllAction()
    setIsPlaying(false)
    currentActionRef.current = null
  }

  return (
    <div style={{ height: "100%", width: "100%", position: 'relative' }}>
      <Canvas
        style={{ background: 'transparent', height: '100%', width: '100%' }}
        camera={{ position: [-0.5, 1, 3] }}
        gl={{ alpha: true }}
        onCreated={({ gl }) => {
          gl.setClearAlpha(0)
        }}
      >
        <Orbit />
        <MixerUpdater mixerRef={mixerRef} />
        {/* 进一步微调脚底与容器底边的距离，向下为负值 */}
        <group ref={mySelfRef} position={[0, -1.5, 0]}>
          <hemisphereLight intensity={0.15} groundColor="black" />
          <ambientLight />
          <primitive object={model.scene} scale={1.3} />
        </group>
      </Canvas>
      {/* 控制面板 */}
      <div style={{ position: 'absolute', left: 8, bottom: 8, display: 'flex', gap: 8, alignItems: 'center' }}>
        <select
          value={selectedAction}
          onChange={(e) => {
            const value = e.target.value
            setSelectedAction(value)
            playAction(value)
          }}
          style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid #666', background: '#fff' }}
        >
          {availableActions.map(name => (
            <option key={name} value={name}>{name}</option>
          ))}
        </select>
        <button
          onClick={handleStop}
          disabled={!isPlaying}
          style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid #666', background: '#fff', cursor: 'pointer' }}
        >停止</button>
      </div>
    </div>

  )
}
export default MySelf